"""
Case Type   : 操作系统类-文件系统故障
Case Name   : 级联备build时 注入故障硬连接数满
Create At   : 2021/7/19
Owner       : @wan005
Description :
    1、将备1build为级联备
    2、级联备注入硬连接数满故障
    3、级联备上执行gs_ctl build
    4、清理故障，
    5、再次build
    6、执行TPCC
    7、检查数据一致性
    8、恢复环境
Expect      :
    1、将备1build为级联备成功
    2、故障注入成功
    3、build失败
    4、清理故障成功
    5、build成功
    6、执行TPCC成功
    7、数据一致
    8、恢复环境
History     :
    Modified by @wan005 2021/12/9: 优化用例增加故障注入耗时
"""
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node, macro


class ReliabilityFileSystem(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.primary_sh = CommonSH(self.nodes[0])
        self.sta_1_sh = CommonSH(self.nodes[1])
        self.sta_2_sh = CommonSH(self.nodes[2])
        self.primary_root_node = Node(node="PrimaryRoot")
        self.sta1_root_node = Node(node="Standby1Root")
        self.sta1_node = Node(node="Standby1DbUser")
        self.constant = Constant()
        self.com = Common()
        self.log.info("setUp-实例化:ok")

        self.log.info("Opengauss_Reliability_OS_File_System_Case023:开始执行")
        self.file_name = f"{macro.DB_INSTANCE_PATH}/postgresql.conf"
        self.inject_cmd = f"rfile_ldeplenish_workmode " \
                          f"(filename, workmode) " \
                          f"values ({self.file_name}, fore)"
        self.clean_cmd = f"rfile_ldeplenish_workmode where " \
                         f"filename={self.file_name} and workmode=fore"

    def test_main(self):
        text = "--step1:将备1 build为级联备;expect:成功"
        self.log.info(text)
        result = self.sta_1_sh.executeGsctl("build",
                                            "server started",
                                            param="-M cascade_standby",
                                            get_detail=True)
        self.log.info(result)
        self.assertIn("server started", result, "执行失败" + text)

        status = self.sta_1_sh.exec_refresh_conf()
        self.assertTrue(status, "执行失败" + text)

        status = self.sta_1_sh.getDbClusterStatus("detail")
        self.log.info(status)
        self.assertIn("S Cascade Normal", status, "执行失败" + text)

        try:
            text = "--step2:级联备注入硬连接数满故障;expect:成功"
            self.log.info(text)
            self.log.info("注入故障")
            session = ComThread(self.com.cfe_inject,
                                args=(self.sta1_root_node,
                                      self.inject_cmd))
            session.setDaemon(True)
            session.start()

            session.join(60 * 30)
            result = session.get_result()
            self.log.info(result)
            self.assertIn("successful execution", result, "执行失败" + text)

            text = "--step3:级联备上执行gs_ctl build;expect:失败"
            self.log.info(text)
            result = self.sta_1_sh.executeGsctl("build",
                                                "server started",
                                                param="-M cascade_standby",
                                                get_detail=True)
            self.log.info(result)
            self.assertIn("failed", result, "执行失败" + text)
            self.assertNotIn("server started", result, "执行失败" + text)

        finally:
            text = "--step4:清除故障;expect:成功"
            self.log.info(text)
            res = self.com.cfe_clean(self.sta1_root_node,
                                     self.clean_cmd)
            self.log.info(res)
            self.assertIn("successful execution", res, "执行失败" + text)

        text = "--step5:故障清理后，级联备上再次执行gs_ctl build;expect:成功"
        self.log.info(text)
        result = self.sta_1_sh.executeGsctl("build",
                                            "server started",
                                            param="-M cascade_standby",
                                            get_detail=True)
        self.log.info(result)
        self.assertIn("server started", result, "执行失败" + text)

        self.log.info("恢复环境")
        result = self.sta_1_sh.executeGsctl("build",
                                            "server started",
                                            param="-b full",
                                            get_detail=True)
        self.log.info(result)
        self.assertIn("server started", result, "执行失败" + text)
        result = self.sta_2_sh.executeGsctl("build",
                                            "server started",
                                            param="-b full",
                                            get_detail=True)
        self.log.info(result)
        self.assertIn("server started", result, "执行失败" + text)

        status = self.sta_1_sh.exec_refresh_conf()
        self.assertTrue(status, "执行失败" + text)

        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        self.assertTrue("Degraded" in db_status
                        or "Normal" in db_status, "执行失败" + text)

        text = "--step6:运行TPCC;expect:成功"
        self.log.info(text)
        result = self.com.startTPCC(self.primary_root_node, macro.TPCC_PATH)
        self.log.info(result)
        self.assertIn(self.constant.TPCC_SUCCESS_MSG, result, "执行失败" + text)

        self.log.info("检查主备是否同步")
        time.sleep(10)
        self.log.info("获取节点数量")
        node_num = self.primary_sh.get_node_num()
        res = self.primary_sh.check_location_consistency("primary", node_num)
        self.assertTrue(res, "执行失败" + text)

        text = "--step7:检查数据一致性;expect:成功"
        self.log.info(text)
        nodes = (Node(self.nodes[0]), Node(self.nodes[1]),
                 Node(self.nodes[2]))
        flag = self.com.check_data_sample_by_all(r'\d', *nodes)
        self.assertTrue(flag, "执行失败" + text)
        table_dict = self.com.format_sql_result(
            self.primary_sh.executDbSql(r'\d'))
        table_name = table_dict.get('Name')
        for name in table_name:
            select_sql = f"select count(*) from {name};"
            flag = self.com.check_data_sample_by_all(select_sql, *nodes)
            self.assertTrue(flag, "执行失败" + text)

    def tearDown(self):
        text = "--step8:环境清理;expect:成功"
        self.log.info(text)
        res = self.com.cfe_clean(self.sta1_root_node,
                                 self.clean_cmd)
        self.log.info(res)

        status = self.sta_1_sh.getDbClusterStatus("detail")
        self.log.info(status)
        if "S Cascade Normal" in status:
            result = self.sta_1_sh.executeGsctl("build",
                                                "server started",
                                                param="-b full",
                                                get_detail=True)
            self.log.info(result)
            status = self.sta_1_sh.exec_refresh_conf()
            self.log.info(status)
        status = self.sta_1_sh.getDbClusterStatus("detail")
        self.log.info(status)

        self.log.info("检查备机是否需要重建")
        result = self.primary_sh.check_whether_need_build()
        success_msg = self.constant.BUILD_SUCCESS_MSG
        if result:
            result = self.sta_1_sh.executeGsctl("build",
                                                success_msg,
                                                "-b full")
            self.log.info(status)
            result = self.sta_2_sh.executeGsctl("build",
                                                success_msg,
                                                "-b full")
            self.log.info(status)

        self.assertIn("successful execution", res, "执行失败" + text)
        self.log.info("故障已清理")
        self.log.info("Opengauss_Reliability_OS_File_System_Case023:执行完成")
